package com.org.manhu.chargehelper.update;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 * @文件名：Update.java
 * @包名：com.coward.callbackwebservice
 * @作者：李朋辉 @QQ：892839211
 * @创建时间：2015年2月28日 上午11:29:18
 *
 * @描述：用于更新的实体类
 */
@SuppressLint({ "HandlerLeak", "RtlHardcoded" })
public class Update implements UpdateInterface {
	
	/** 上下文环境 **/
	private Context activity;

	/** 更新内容文本地址 **/
	private String version_url;

	/** 更新信息 **/
	private UpdateInfo updateInfo;

	/** apk在本地存放的路径 **/
	private String dir_path;

	/** 当前版本号 **/
	private int current_version;

	/** 更新进度对话框 **/
	AlertDialog download_dialog;

	/** 更新进度条 **/
	private ProgressBar update_progreseBar;

	/** 更新进度对话框中的进度更新提示textview **/
	private TextView textView;

	/** 当前进度 **/
	private int progress;

	/** 更新进度提示对话框中的提示文本 **/
	private String text;

	/** 开始下载 **/
	private static final int DOWNLOAD_INVOKE = 0x001;

	/** 下载完成 **/
	private static final int DOWNLOAD_FINISHED = 0x002;

	private static final int NET_ERROR = 0x003;

	private SharedPreferences update_settings;

	private static final int NO_INVOKE = 0;

	private static final int ON_INVOKE = 1;

	private static final int NO_DOWNLOAD = 0;

	private static final int ON_DOWNLOAD = 1;

	/** 通知是否发出 **/
	private boolean notificationHasSend = false;

	/** 是否使用通知 **/
	private boolean useNitification = false;

	private Notification notification;

	/** 更新的新版本的描述 */
	private StringBuilder updateContent;

	private volatile static Update singleton = null;
	
	/**
	 * @param activity
	 *            上下文环境
	 * @param version_url
	 *            更新内容文本地址
	 * @param current_version
	 *            当前版本号
	 */
	public static Update getInstance(Context activity, String version_url,
			int current_version) {
		if (singleton == null) {
			synchronized (Update.class) {
				if (singleton == null) {
					singleton = new Update(activity, version_url,
							current_version);
				}
			}
		}
		return singleton;
	}

	/**
	 * @param activity
	 *            上下文环境
	 * @param version_url
	 *            更新内容文本地址
	 * @param current_version
	 *            当前版本号
	 */
	private Update(Context activity, String version_url, int current_version) {
		this.activity = activity;
		this.version_url = version_url;
		this.current_version = current_version;
		this.update_settings = activity.getSharedPreferences("update",
				Activity.MODE_PRIVATE);
	}

	/**
	 * 判断是否有新版本
	 * 
	 * @throws Exception
	 */
	@Override
	public boolean isUpdate() throws Exception {
		if (UpdateUtil.checkNetwork(activity)) {
			return getNewVersion() > current_version ? true : false;
		}
		return false;
	}

	/**
	 * @描述：设置notification是否可用，默认不可用
	 * @param useable
	 */
	public void notificationAvailable(boolean useable) {
		this.useNitification = useable;
	}
	
	private void getVersionText() throws Exception {
		HttpURLConnection urlConn = (HttpURLConnection) new URL(version_url)
				.openConnection();
		urlConn.setDoInput(true);
		urlConn.setUseCaches(false);
		urlConn.setConnectTimeout(3000);// 设置连接超时
		InputStream in = urlConn.getInputStream();
		updateInfo = ParseXml.parseXml(in);
		urlConn.disconnect();
		in.close();
		String description = updateInfo.getDescription();
		String[] tips = description.split(";");
		updateContent = new StringBuilder();
		updateContent.append("更新内容：\n");
		for (int i = 0; i < tips.length; i++) {
			if (i != tips.length - 1) {
				updateContent.append(tips[i] +"；"+ "\n");
			} else {
				updateContent.append(tips[i]);
			}
		}
	}

	/**
	 * @描述：下载并获取服务器上版本文件的版本信息
	 * @return
	 * @throws IOException
	 */
	private int getNewVersion() throws Exception {
		getVersionText();
		int serverVersion = updateInfo.getVersionCode();
		return serverVersion;
	}

	/**
	 * @描述：开启线程下载应用
	 */
	private void downloadApk() {
		new DownloadApkThread().start();
	}

	/**
	 * @描述：删除未下载完的文件并重置更新的配置文件
	 */
	protected void reset() {
		// TODO Auto-generated method stub
		File file = new File(dir_path, updateInfo.getAppName());
		if (file.exists()) {
			file.delete();
		}
		update_settings.edit().clear().commit();
	}
	
	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case DOWNLOAD_INVOKE:
				update_progreseBar.setProgress(progress);
				textView.setText(text);
				break;
			case DOWNLOAD_FINISHED:
				installApk();
				((Activity) activity).finish();
				break;
			case NET_ERROR:// 网络连接异常的情况，让dialog消失同时删除文件并清空更新配置，同时发送通知提示更新失败
				if (useNitification) {
					showNotification(0);
				}
				download_dialog.dismiss();// 隐藏更新进度对话框
				reset();
				break;
			default:
				break;
			}
		};
	};

	/**
	 * @文件名：IUpdateUtilsImpl.java
	 * @包名：com.org.manhu.updateutils
	 * @作者：李朋辉 @QQ：892839211
	 * @创建时间：2015年1月6日 下午4:22:28、
	 *
	 * @描述：用于更新apk的线程的实体类
	 */
	private class DownloadApkThread extends Thread {
		@Override
		public void run() {
			try {
				// 判断SD卡是否可用
				if (Environment.getExternalStorageState().equals(
						Environment.MEDIA_MOUNTED)) {
					// apk文件的保存路径
					dir_path = Environment.getExternalStorageDirectory()
							+ "/download";
					URL url = new URL(updateInfo.getDownUrl());
					// 打开连接
					HttpURLConnection conn = (HttpURLConnection) url
							.openConnection();
					conn.connect();
					// 获取下载文件的长度
					int length = conn.getContentLength();
					// 获取输入流
					InputStream in = conn.getInputStream();

					File file = new File(dir_path);
					// 判断文件是否存在
					if (!file.exists()) {
						file.mkdir();
					}
					File apk_file = new File(dir_path, updateInfo.getAppName());
					FileOutputStream fileOut = new FileOutputStream(apk_file);
					int count = 0;
					byte[] buffer = new byte[1024];
					do {
						if (UpdateUtil.checkNetwork(activity)) {
							int numread = in.read(buffer);
							count += numread;
							// 计算进度
							progress = (int) (((float) count / length) * 100);
							text = UpdateUtil.convertToMB(count) + "/"
									+ UpdateUtil.convertToMB(length);
							// 发送消息
							mHandler.sendEmptyMessage(DOWNLOAD_INVOKE);

							if (numread <= 0) {
								// 下载完成
								download_dialog.dismiss();
								mHandler.sendEmptyMessage(DOWNLOAD_FINISHED);
								break;
							}
							fileOut.write(buffer, 0, numread);
						} else {
							if (!notificationHasSend) {
								mHandler.sendEmptyMessage(NET_ERROR);
								notificationHasSend = true;
							}
						}
					} while (!notificationHasSend);
					fileOut.close();
					in.close();
				}
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @描述：安装下载好的apk文件
	 */
	private void installApk() {
		File apk_file = new File(dir_path, updateInfo.getAppName());
		if (!apk_file.exists()) {
			return;
		}
		// 清空更新配置文件
		update_settings.edit().clear().commit();
		Intent install_apk = new Intent(Intent.ACTION_VIEW);
		install_apk.setDataAndType(Uri.parse("file://" + apk_file.toString()),
				"application/vnd.android.package-archive");
		activity.startActivity(install_apk);
	}

	/**
	 * @描述：初始化notification
	 * @param title
	 *            notification 的标题
	 * @param content
	 *            notification 的内容
	 * @param iconId
	 *            notification 的图标
	 */
	@SuppressWarnings("deprecation")
	public void initNOtification(String title, String content, int iconId) {
		// 创建一个Notification
		notification = new Notification();
		// 设置通知 消息 图标
		notification.icon = iconId;
		// 设置发出消息的内容
		notification.tickerText = "";
		// 设置发出通知的时间
		notification.when = System.currentTimeMillis();

		// 设置显示通知时的默认的发声、振动、Light效果
		notification.defaults = Notification.DEFAULT_ALL;

		// PendingIntent android系统负责维护
		PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0,
				((Activity) activity).getIntent(), 0);
		// 设置更加详细的信息
		if (TextUtils.isEmpty(title)) {
			title = "更新失败";
		}
		if (TextUtils.isEmpty(content)) {
			content = updateInfo.getAppName() + "更新失败";
		}
		notification
				.setLatestEventInfo(activity, title, content, pendingIntent);
	}
	
	/**
	 * @描述：更新过程中出现网络异常的时候发送的notification
	 */
	public void showNotification(int notificationId) {

		NotificationManager notificationManager = (NotificationManager) activity
				.getSystemService(Context.NOTIFICATION_SERVICE);
		// 使用notificationManager对象的notify方法 显示Notification消息 需要制定
		// Notification的标识
		notificationManager.notify(notificationId, notification);

	}
	
	/**
	 * 获取新版本的更新提示对话框
	 */
	@Override
	public AlertDialog getUpdateDialog(final Context act) {
		if (update_settings.getInt("update_count", 0) == NO_INVOKE) {
			AlertDialog mDialog = null;
			AlertDialog.Builder builder = new AlertDialog.Builder(act);
			builder.setIcon(android.R.drawable.ic_dialog_info);
			builder.setTitle("发现新版本是否更新?");
			builder.setMessage((CharSequence) updateContent);
			builder.setPositiveButton("立即更新", new OnClickListener() {
				@Override
				public void onClick(DialogInterface paramDialogInterface,
						int paramInt) {
					update_settings.edit().putInt("update_count", ON_INVOKE)
							.commit();
					// 更新进度dialog
					showDownloadDialog(act);
				}
			}).setNegativeButton("以后再说", new OnClickListener() {
				@Override
				public void onClick(DialogInterface paramDialogInterface,
						int paramInt) {
				}
			});
			mDialog = builder.create();
			mDialog.show();
			return mDialog;
		} else {
			return null;
		}
	}
	
	/**
	 * @描述：显示更新进度对话框
	 * @param act
	 */
	private void showDownloadDialog(Context act) {
		AlertDialog.Builder builder = new Builder(act);
		builder.setTitle("正在更新\t\t\t\t\t\t\t\t\t\t\t");
		LinearLayout view = new LinearLayout(act);
		view.setOrientation(LinearLayout.VERTICAL);
		view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT));
		view.setPadding(10, 0, 10, 0);
		update_progreseBar = new ProgressBar(act, null,
				android.R.attr.progressBarStyleHorizontal);
		update_progreseBar.setLayoutParams(new LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
		view.addView(update_progreseBar);

		textView = new TextView(act);
		textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.WRAP_CONTENT));
		textView.setPadding(0, 5, 0, 5);
		textView.setGravity(Gravity.RIGHT);
		view.addView(textView);

		update_progreseBar.setMax(100);
		builder.setView(view);
		download_dialog = builder.create();
		download_dialog.setCancelable(false);
		download_dialog.show();

		if (update_settings.getInt("download_count", 0) == NO_DOWNLOAD) {
			update_settings.edit().putInt("download_count", ON_DOWNLOAD)
					.commit();
			downloadApk();
		}
	}

}
